package com.yl.chainStore.config

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.ser.std.DateSerializer
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.yl.chainStore.interceptor.UserPowerInterceptor
import com.yl.chainStore.interceptor.WebContextInterceptor
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import java.io.IOException
import java.text.ParseException
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.jvm.Throws


@Configuration
open class ConfigInterceptor : WebMvcConfigurer {

	@Value("\${config.file-save-path}")
	private val fileSavePath: String? = null

	//相对路径
	@Value("\${config.resources-rootPath}")
	private val resourcesRootPath: String? = null




	/**
	 * author:吴枫
	 * description:配置资源映射
	 * 意思是：如果访问的资源路径是以 " $resourcesRootPath "开头的，
	 * 就给我映射到本机的“ $fileSavePath ”这个文件夹内，去找你要的资源
	 * 注意：$fileSavePath 后面的 “/”一定要带上
	 */
	override fun addResourceHandlers(registry: ResourceHandlerRegistry) {

		registry.addResourceHandler("$resourcesRootPath**")
				.addResourceLocations("file:$fileSavePath")
	}

	@Bean
	open fun getWebContextInterceptor(): WebContextInterceptor {
		return WebContextInterceptor()
	}

	@Bean
	open fun getUserPowerInterceptor(): UserPowerInterceptor {
		return UserPowerInterceptor()
	}

	override fun addInterceptors(registry: InterceptorRegistry) {
		registry.addInterceptor(getWebContextInterceptor()).addPathPatterns("/**")
			.excludePathPatterns("/sys/index/login")
			.excludePathPatterns("/sys/index/test")
			.excludePathPatterns("/resources/**")
			.excludePathPatterns("/phone/customer/info/**")

		//这里对部分不需要拦截的进行取消
		registry.addInterceptor(getUserPowerInterceptor()).addPathPatterns("/**")
			.excludePathPatterns("/sys/index/login")
			.excludePathPatterns("/sys/index/test")
			.excludePathPatterns("/resources/**")
			.excludePathPatterns("/phone/customer/info/**")
	}

//	@Bean
//	open fun enumCustomizer(): Jackson2ObjectMapperBuilderCustomizer {
//		return Jackson2ObjectMapperBuilderCustomizer { jacksonObjectMapperBuilder ->
//			jacksonObjectMapperBuilder.serializerByType(ErrorCode::class.java, object : JsonSerializer<ErrorCode>() {
//				@Throws(IOException::class)
//				override fun serialize(value: ErrorCode, gen: JsonGenerator, serializers: SerializerProvider?) {
//					gen.writeNumber(value.code)
//					gen.writeStringField("hint", value.hint)
//				}
//			})
//		}
//	}

	override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
		val objectMapper: ObjectMapper = serializingObjectMapper()

		converters.removeIf { it is MappingJackson2HttpMessageConverter }

		converters.add(MappingJackson2HttpMessageConverter(objectMapper))
	}
}


private fun serializingObjectMapper(): ObjectMapper {
	val objectMapper = jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
	val timeModule = JavaTimeModule()
	val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
	val dataFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
	timeModule.addSerializer(LocalDateTime::class.java, LocalDateTimeSerializer(dataFormat))
	timeModule.addSerializer(LocalDate::class.java, LocalDateSerializer(dataFormat))
	timeModule.addSerializer(LocalTime::class.java, LocalTimeSerializer(dataFormat))
	timeModule.addSerializer(Date::class.java, DateSerializer(false, simpleDateFormat))
	//反序列化日期格式
	timeModule.addDeserializer(LocalDateTime::class.java, LocalDateTimeDeserializer(dataFormat))
	timeModule.addDeserializer(LocalDate::class.java, LocalDateDeserializer(dataFormat))
	timeModule.addDeserializer(LocalTime::class.java, LocalTimeDeserializer(dataFormat))
	timeModule.addDeserializer(Date::class.java, object : JsonDeserializer<Date>() {
		@Throws(IOException::class)
		override fun deserialize(jsonParser: JsonParser, deserializationContext: DeserializationContext?): Date? {
			return try {
				if(jsonParser.text.isNullOrEmpty()){
					return null
				}
				if(jsonParser.text == null ||jsonParser.text.isEmpty() ){
					null
				}else{
					simpleDateFormat.parse(jsonParser.text)
				}

			} catch (e: ParseException) {
				throw RuntimeException(e)
			}
		}
	})
	objectMapper.registerModule(timeModule)
//	objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
	objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
	return objectMapper
}
